package com.scarecrow.olga.asset {
	
	import com.scarecrow.olga.util.Cache;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	
	/**
	 * ...
	 * @author Santiago.J.Elizalde
	 */
	public class Asset extends EventDispatcher {
		
		private static var assetCache:Cache;
		
		private var assetLoader:Loader;
		private var assetDomain:ApplicationDomain;
		private var assetURL:String;
		
		private var useCache:Boolean;
		
		public function Asset(urlPath:String, skipCache:Boolean=false) {
			
			useCache = !skipCache;
			assetURL = urlPath;
			
			if (useCache) {
				if (!assetCache) {
					assetCache = new Cache();
				}
				if (!assetCache.hasObject(urlPath)) {
					assetCache.addObject(new Loader(), urlPath);
				}
				assetLoader = assetCache.getObject(assetURL);
				if (isLoaded) {
					assetDomain = assetLoader.contentLoaderInfo.applicationDomain;
				}
			} else {
				assetLoader = new Loader();
			}
		}
		
		/**
		 * Loads the URL provided to this Asset.
		 * 
		 * NOTE: 	If anyone else has started loading the same URL and is using 
		 * 			the cache, the loading process will be reset, for cache security reasons.
		 */
		public function load():void {
			if (isLoaded) return;
			if (useCache && !loadingInProgress) {
				// This is used to restart the loader if anyone started a load operation in the same frame, to be sure 
				//that everyone will receive the content. it is needed due to laoder sharing through the cache.
				assetLoader.close();
			}
			assetLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
			assetLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
			if(!loadingInProgress) assetLoader.load(new URLRequest(assetURL));
		}
		
		public function get loadingInProgress():Boolean {
			var loaded:uint = this.assetLoader.contentLoaderInfo.bytesLoaded
			return  loaded != 0 && !isLoaded;
		}
		public function get isLoaded():Boolean {
			return this.assetLoader.contentLoaderInfo.bytesTotal == assetLoader.contentLoaderInfo.bytesLoaded;
		}
		
		
		public function hasDefinition(definitionName:String):Boolean {
			if (!assetDomain) {
				return false;
			}
			return assetDomain.hasDefinition(definitionName);
		}
		
		public function getInstanceByName(definitionName:String):DisplayObject {
			
			if (!assetDomain) {
				return false;
			}
			
			var instance:DisplayObject = null;
			if (hasDefinition(definitionName)) {
				instance = assetDomain.getDefinition(definitionName);
			}
			return instance;
		}
		
		public function get url():String {
			return this.assetURL;
		}
		
		public function get content():DisplayObject {
			return assetLoader.content;
		}
		
		public function destroy(clearCache:Boolean=false):void {
			assetDomain = null;
			assetLoader = null;
			if (!skipCache) assetCache.flushObject(this.assetURL);
		}

		private function onIOError(e:IOErrorEvent):void {
			trace("[WARNING]@Asset.load() :: Loading of asset at URL '" + assetURL + "' failed. Nested exception is: " + "\n" + e.text);
		}
		
		private function onComplete(e:Event):void {
			trace("[INFO] Asset loaded successfully [" + assetURL + "]");
			assetDomain = assetLoader.contentLoaderInfo.applicationDomain;
		}
	}
}













